# client.py
# - this is the main executable to launch the yapss server
import logging
#logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)-8s %(message)s')
logging.basicConfig(level=logging.INFO, format='%(levelname)-8s %(message)s')
import wx, sys
import pysage
from pysage import ActorManager, Actor
from views.window import Window
from presenters.menupresenter import MenuPresenter
from presenters.albumpresenter import AlbumPresenter
from presenters.thumbnailpresenter import ThumbnailPresenter
from controllers.albumcontroller import AlbumController
from controllers.thumbnailcontroller import ThumbnailController
from controllers.resourcecontroller import ResourceController
from controllers.metadatacontroller import MetaDataAPI
from controllers.resourceparser import ResourceParser
from controllers.servercontroller import ServerController
from controllers.menucontroller import MenuController
from messages import *
import util

omanager = ActorManager.get_singleton()

logger = pysage.get_logger()

class Ticker(wx.Timer):
    def Notify(self):
        start = util.get_time()
        omanager.tick(max_time = .01)
        duration = util.get_time() - start
        if duration > .01:
            logger.debug('duration is more than .01 sec (duration %s)' % duration)

class Application(wx.App, Actor):
    subscriptions = ['CloseApplicationMessage']
    def __init__(self, *args, **kws):
        wx.App.__init__(self, *args, **kws)
        Actor.__init__(self)
        self._SYNC_PRIORITY = 10
    def OnInit(self):
        self.prepare()
        omanager.find('window').Show(True)
        self.SetTopWindow(omanager.find('window'))
        return True
    def prepare(self):
        # starting groups (threads)
        # we will create a separate thread for resource loading
        
        # responsiveness:
        # each tick can take as long as .01 second, can only process 1 message if takes longer
        # we need to check as soon as possible, but maintain a minimum sleep time so that the GUI can be responsive
#        if sys.platform == 'darwin':
#            omanager.add_group('resource_loading', max_tick_time=.01, minimum_sleep=.1)
#        else:
#            omanager.add_group('resource_loading', max_tick_time=.01, minimum_sleep=.01)
        
        # APIs
        omanager.register_actor(MetaDataAPI(), 'mapi')
        
        # presenters
        omanager.register_actor(MenuPresenter(), 'menupresenter')
        omanager.register_actor(AlbumPresenter(), 'albumpresenter')
        omanager.register_actor(ThumbnailPresenter(), 'thumbnailpresenter')
        
        # controllers
        omanager.register_actor(ThumbnailController(), 'thumbnailcontroller')
        omanager.register_actor(ResourceParser(), 'resourceparser')
        omanager.register_actor(AlbumController(), 'albumcontroller')
        omanager.register_actor(ServerController(), 'servercontroller')
        omanager.register_actor(MenuController(), 'menucontroller')
        
        # views
        omanager.register_actor(Window(None, -1, "Yapss", size=(900, 600)), 'window')
        
        # register a controller with the worker thread
        omanager.add_process_group('resource_loading', ResourceController)
#        omanager.register_actor(ResourceController(), 'resourcecontroller')
        
        # load all data
        omanager.trigger(InitializeAlbumsDataMessage())
        # load the albums viewer pane
        omanager.trigger(InitializeAlbumsViewerMessage())
        if omanager.find('mapi').get_albums():
            omanager.queue_message(AlbumSelectedMessage(albumid = omanager.find('mapi').get_albums()[0].id))
            omanager.queue_message_to_group('resource_loading', AlbumSelectedMessage(albumid = omanager.find('mapi').get_albums()[0].id))
            
        self.timer = Ticker()
        self.timer.Start(25)
            
        return True
    def handle_CloseApplicationMessage(self, msg):
        self.timer.Stop()
        omanager.find('window').Close(True)
        omanager.find('window').Destroy()
        omanager.reset()
        return True
        
if __name__ == '__main__':
    # Import Psyco if available
#    try:
#        import psyco
#        psyco.full()
#        logger.warn('using psyco')
#    except ImportError:
#        logger.warn('psyco is not available')

    import processing
    processing.freezeSupport()
    app = omanager.register_actor(Application(0), 'application')
    app.MainLoop()

